/*
 * @Author: 9ilk 3535851673@qq.com
 * @Date: 2025-01-15 20:36:53
 * @LastEditors: 9ilk 3535851673@qq.com
 * @LastEditTime: 2025-01-18 17:23:57
 * @FilePath: /zhuang/TCP/EchoServer/TcpClient.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include<cstring>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include"Protocol.hpp" //双方立马形成约定!
#include<arpa/inet.h>
#include<iostream>
#include<unistd.h>
using namespace std;

//./client_tcp
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        cout << "Usage:./client_tcp  server_ip  server_port\n";
        return 1;
    }
    string server_ip = argv[1];
    int server_port = atoi(argv[2]);
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        cout << "create socket failed\n";
        return 2;
    }
    //填充套接字地址结构体
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port);//主机转网络序列
    server_addr.sin_addr.s_addr = inet_addr(server_ip.c_str());//点分式字符串风格ip地址转换为网络字节序
    //client 不需要显示进行bind --- 
    //需要操作系统进行自动绑定 客户端连别人,别人不可能连它 --- connect的时候系统自动分配端口
    //首次连接自动bind
    int n = ::connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
    if(n < 0)
    {
        cout << "connect failed\n";
        return 3;
    }
    //连接成功
    string message;
    while(true)
    {  //发消息
        int x,y;
        char oper;
        cout << "input x: ";
        cin >> x;
        cout << "input y: ";
        cin >> y;
        cout << "input x: ";
        cin >> oper;
        //构建request
        Request req(x,y,oper);

        //1.序列化
        req.Serializze(message);

        //2.添加报头 Encode
        EnCode(message); 

        //3.发送message
        n = send(sockfd,message.c_str(),message.size(),0);
        if(n > 0) 
        {   
            char inbuffer[1024]; 
            //4.读取应答
            int m = ::recv(sockfd,inbuffer,sizeof(inbuffer),0);
            if(m > 0)
            {  //读取成功
                inbuffer[m] = 0;
                string package = inbuffer;
                string content;
                ///认为读到的应答暂定是完整的->5.解析Decode
                Decode(package,&content);
                //6.反序列化
                Response resp;
                resp.Deserializze(content); //得到结构化数据
                //7.处理结构化数据
                cout << resp.Result() << " [" << resp.Code() << "]" << endl;
            }
            else
             break;
        }
        else
         break;
    }
   ::close(sockfd); 
  return 0;
}